/*
 * Copyright (c) 2018 Hitevision
 */

package tw.com.hitevision.whiteboard.android.state;

import android.content.Context;
import android.graphics.PointF;
import android.util.Log;

import java.util.List;

import tw.com.hitevision.whiteboard.android.render.Autoshape;
import tw.com.hitevision.whiteboard.android.render.BaseItem;
import tw.com.hitevision.whiteboard.android.render.Word;

/**
 * This class contains transformation parameters for {@link BaseItem}s.  Transformations are
 * performed by calling {@link #apply(List)}.
 */
public class Transform {
    private static final String TAG = Transform.class.getSimpleName();

    private float rotate;
    private float scaleX;
    private float scaleY;
    private PointF scalePoint;
    private PointF rotatePoint;
    private float translateX;
    private float translateY;

    public Transform(Context context) {
        rotate = 0.0f;
        scaleX = 1.0f;
        scaleY = 1.0f;
        translateX = 0.0f;
        translateY = 0.0f;
        scalePoint = new PointF();
        rotatePoint = new PointF();
    }

    /**
     * Resets the transformation parameters.
     */
    public void clear() {
        rotate = 0.0f;
        scaleX = 1.0f;
        scaleY = 1.0f;
        translateX = 0.0f;
        translateY = 0.0f;
        scalePoint.set(0, 0);
        rotatePoint.set(0, 0);
    }

    /**
     * Transforms an array of {@code BaseItem}s.
     */
    public void apply(List<BaseItem> items) {
        log("apply");
        log("- translateX=" + translateX + ", translateY=" + translateY + ", scaleX=" + scaleX + ", scaleY=" + scaleY + ", rotate=" + rotate);
        log("- scalePoint=" + scalePoint + ", rotatePoint=" + rotatePoint);
        for (BaseItem item : items) {
            if ((scaleX != 1 && scaleX!=0 ) || (scaleY != 1&&scaleY!= 0)) {
                if (item instanceof Word) {
                    ((Word) item).quickSaveWordState();
                }

                float itemScaleX = scaleX;
                float itemScaleY = scaleY;

                item.scaleFromPoint(itemScaleX, itemScaleY, scalePoint);
            }

            if (translateX != 0 || translateY != 0) {
                item.moveBy(translateX, translateY);
            }

            if (rotate != 0) {
                item.rotateFromPoint(rotate, rotatePoint);
            }

            if(item instanceof Autoshape){
                if(((Autoshape) item).getType()== AutoshapeProperty.Type.ARROW){
                    ((Autoshape) item).rebuildArrow();
                }
            }
        }
    }

    public void apply(BaseItem item){
        if ((scaleX != 1 && scaleX!=0 ) || (scaleY != 1&&scaleY!= 0)) {
            if (item instanceof Word) {
                ((Word) item).quickSaveWordState();
            }

            float itemScaleX = scaleX;
            float itemScaleY = scaleY;

            item.scaleFromPoint(itemScaleX, itemScaleY, scalePoint);
        }

        if (translateX != 0 || translateY != 0) {
            item.moveBy(translateX, translateY);
        }

        if (rotate != 0) {
            item.rotateFromPoint(rotate, rotatePoint);
        }

        if(item instanceof Autoshape){
            if(((Autoshape) item).getType()== AutoshapeProperty.Type.ARROW){
                ((Autoshape) item).rebuildArrow();
            }
        }
    }

    public void setRotatePoint(float x, float y) {
        rotatePoint.x = x;
        rotatePoint.y = y;
    }

    /**
     * Returns the rotation in degrees.
     */
    public float getRotate() {
        return rotate;
    }

    /**
     * Sets the rotation in degrees.
     */
    public void setRotate(float deg) {
        this.rotate = deg;
    }

    /**
     * Adjusts the rotation by the specified amount in degrees.
     */
    public void rotateBy(float deg) {
        rotate += deg;
    }

    public void setScalePoint(float x, float y) {
        scalePoint.x = x;
        scalePoint.y = y;
    }

    public float getScaleX() {
        return scaleX;
    }

    public float getScaleY() {
        return scaleY;
    }

    public void setScale(float scaleX, float scaleY) {
        this.scaleX = scaleX;
        this.scaleY = scaleY;
    }

    public void setTranslate(float translateX, float translateY) {
        this.translateX = translateX;
        this.translateY = translateY;
    }

    public float getTranslateX() {
        return translateX;
    }

    public void setTranslateX(float translateX) {
        this.translateX = translateX;
    }

    public float getTranslateY() {
        return translateY;
    }

    public void setTranslateY(float translateY) {
        this.translateY = translateY;
    }

    public PointF getRotatePoint() {
        return rotatePoint;
    }

    public PointF getScalePoint() {
        return scalePoint;
    }

    public void moveBy(float dx, float dy) {
        translateX += dx;
        translateY += dy;
    }

    private static void log(String msg) {
        Log.d(TAG, msg);
    }
}
